package org.kolonitsky.css.writers;

import org.w3c.css.sac.*;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

/**
 * @author Alex.Kolonitsky
 */
public class SelectorsXmlWriter {

    private final StackXMLStreamWriter writer;
    private final ConditionXmlWriter condWriter;

    public SelectorsXmlWriter(XMLStreamWriter writer) {
        this.writer = new StackXMLStreamWriter(writer);
        this.condWriter = new ConditionXmlWriter(writer);
    }

    public void writeSelector_(Selector selector) throws XMLStreamException {
        writer.writeStartElement("selector");
        writer.writeAttribute("value", selector.toString());

        writeSelectorComplete(selector);

        writer.writeEndElement();
    }

    protected void writeSelectorComplete(Selector selector) throws XMLStreamException {
        int initState = writer.size();

        writeSelector(selector);

        writer.close(initState);
    }
    protected void writeSelector(Selector selector) throws XMLStreamException {
        switch (selector.getSelectorType()) {

            case Selector.SAC_ELEMENT_NODE_SELECTOR:
                String name = ((ElementSelector) selector).getLocalName();
                writer.writeStartElement(name == null ? "some" : name);
                break;

            /**
             * This selector matches an arbitrary descendant of some ancestor element.
             * example:
             * <pre class="example">
             *   E F
             * </pre>
             * @see DescendantSelector
             */
            case Selector.SAC_DESCENDANT_SELECTOR:
                writeDescendantSelectors((DescendantSelector) selector);
                break;

            /**
             * This selector matches a childhood relationship between two elements.
             * example:
             * <pre class="example">
             *   E > F
             * </pre>
             * @see DescendantSelector
             */
            case Selector.SAC_CHILD_SELECTOR:
                DescendantSelector dSelector = (DescendantSelector) selector;
                writeSelector(dSelector.getAncestorSelector());
                writeSelector(dSelector.getSimpleSelector());
                writer.writeEndElement();
                break;

            /**
             * This selector matches two selectors who shared the same parent in the
             * document tree and the element represented by the first sequence
             * immediately precedes the element represented by the second one.
             * example:
             * <pre class="example">
             *   E + F
             * </pre>
             * @see SiblingSelector
             */
            case Selector.SAC_DIRECT_ADJACENT_SELECTOR:
                SiblingSelector sSelector = (SiblingSelector) selector;
                writeSelector(sSelector.getSelector());
                writer.writeEndElement();
                writeSelector(sSelector.getSiblingSelector());
                break;

            case Selector.SAC_CONDITIONAL_SELECTOR:
                ConditionalSelector condSel = (ConditionalSelector) selector;
                writeSelector(condSel.getSimpleSelector());
                condWriter.writeCondition(condSel.getCondition());
                break;

            case Selector.SAC_PSEUDO_ELEMENT_SELECTOR:
                writer.writeAttribute("pseudo-selector", ((ElementSelector) selector).getLocalName());
                break;

            case Selector.SAC_ANY_NODE_SELECTOR:
            case Selector.SAC_CDATA_SECTION_NODE_SELECTOR:
            case Selector.SAC_COMMENT_NODE_SELECTOR:
            default:
                writer.writeEmptyElement("sel");
                writer.writeAttribute("type", "" + selector.getSelectorType());
                writer.writeAttribute("value", "" + selector.toString());
                writer.writeEndElement();
                // Do nothing.
        }

    }

    private void writeDescendantSelectors(DescendantSelector selector) throws XMLStreamException {
        writeSelector(selector.getAncestorSelector());

        writer.writeStartElement("any");
        writeSelector(selector.getSimpleSelector());
    }
}
